#!/usr/bin/env bash
unset_env_variables() {
  # The user's build environment might already have pre-set
  # flags that can interfere with the compilation process
  echo "unset_env_variables()"
  unset CPPFLAGS
  unset BOOST_LIB_PATH
  unset BOOST_ROOT
  unset BOOST_LIB_SUFFIX #BOOST_LIB_SUFFIX=-mt
  unset OPENSSL_ROOT_DIR
  unset OPENSSL_BIN_PATH
  unset OPENSSL_INCLUDE_PATH
  unset OPENSSL_LIB_PATH
}
unset_env_variables

LIBRARY_VERSION=`egrep "version '.*'" ../build.gradle | sed "s/[version| ']//g"`
LIBRARY_NAME=jlibtorrent
LIBTORRENT_REVISION=6aad9a463236f0e12f4c4808e4aa84aa0d8b7450 # fix incoming TCP connections when using tracker-only proxy
OPENSSL_VERSION="1.1.1j"
#BOOST_VERSION="74"
BOOST_VERSION="73"
# TEMP NOTES ON BOOST ISSUES, DEC 13 2020
# Reverting to boost 1.73.
# To build on macOS you need to comment the following line on ${BOOST_ROOT}/tools/build/src/tools/darwin.jam
# 'flags darwin.compile.c++ OPTIONS $(condition) : -fcoalesce-templates ;'
# We might have to do this in Travis CI

# 1.74 seems to require -frtti linking
#In file included from /Users/gubatron/src/libtorrent/src/announce_entry.cpp:34:
#In file included from /Users/gubatron/src/libtorrent/include/libtorrent/announce_entry.hpp:41:
#In file included from /Users/gubatron/src/libtorrent/include/libtorrent/socket.hpp:53:
#In file included from /Users/gubatron/src/boost_1_74_0/boost/asio/ip/tcp.hpp:19:
#In file included from /Users/gubatron/src/boost_1_74_0/boost/asio/basic_socket_acceptor.hpp:19:
#In file included from /Users/gubatron/src/boost_1_74_0/boost/asio/any_io_executor.hpp:22:
#In file included from /Users/gubatron/src/boost_1_74_0/boost/asio/execution.hpp:19:
#/Users/gubatron/src/boost_1_74_0/boost/asio/execution/any_executor.hpp:811:12: error: use of typeid requires -frtti
#    return typeid(void);

# 1.75 causes swig to not generate error_code.java and other error handling classes
# With boost 1.75 swig will issue these boost related warnings, something must have changed
# Warning 315: Nothing known about 'boost::system::generic_category'
# 'boost::system::system_category'
BOOST_MAJOR="1"
BOOST_MINOR="0"
SWIG=`pwd`
SRC="${HOME}/src"
BOOST_ROOT="${SRC}/boost_${BOOST_MAJOR}_${BOOST_VERSION}_${BOOST_MINOR}"
LIBTORRENT_ROOT="${SRC}/libtorrent"
OPENSSL_SOURCE="${SRC}/openssl-${OPENSSL_VERSION}"
OPENSSL_ROOT="${SRC}/openssl"
export OPENSSL_NO_OPTS="no-afalgeng no-async no-autoalginit no-autoerrinit no-capieng no-cms no-comp no-deprecated no-dgram no-dso no-dtls no-dynamic-engine no-egd no-engine no-err no-filenames no-gost no-hw no-makedepend no-multiblock no-nextprotoneg no-posix-io no-psk no-rdrand no-sctp no-shared no-sock no-srp no-srtp no-static-engine no-stdio no-threads no-ui-console no-zlib no-zlib-dynamic -fno-strict-aliasing -fvisibility=hidden -Os"

prompt_msg() {
 echo
 echo "============================================================================="
 echo $1
 echo "============================================================================="
 echo
}

press_any_to_continue() {
 if [ ! -n "${DONT_PRESS_ANY_KEY}" ]; then
   echo "[Press any key to continue]"
   read -n 1 -s -r -p ""
 fi
}

create_folder_if_it_doesnt_exist() {
 if [[ ! -d $1 ]]; then mkdir -p $1; fi;
}

abort_if_var_unset() {
  var_name=${1}
  var_value=${2}
  if [[ ! -n ${var_value} ]]; then
    prompt_msg "Error ${var_name} not set. Aborting"
    exit 1
  fi
  echo ${var_name} set to ${var_value}
}

check_min_req_vars() {
  abort_if_var_unset "LIBTORRENT_REVISION" ${LIBTORRENT_REVISION}
  abort_if_var_unset "LIBRARY_VERSION" ${LIBRARY_VERSION}
  abort_if_var_unset "LIBRARY_NAME" ${LIBRARY_NAME}
  abort_if_var_unset "OPENSSL_VERSION" ${OPENSSL_VERSION}
  abort_if_var_unset "BOOST_VERSION" ${BOOST_VERSION}
  abort_if_var_unset "BOOST_MAJOR" ${BOOST_MAJOR}
  abort_if_var_unset "BOOST_MINOR" ${BOOST_MINOR}
  abort_if_var_unset "SWIG" ${SWIG}
  abort_if_var_unset "SRC" ${SRC}
  abort_if_var_unset "BOOST_ROOT" ${BOOST_ROOT}
  abort_if_var_unset "LIBTORRENT_ROOT" ${LIBTORRENT_ROOT}
  abort_if_var_unset "OPENSSL_SOURCE" ${OPENSSL_SOURCE}
  abort_if_var_unset "OPENSSL_ROOT" ${OPENSSL_ROOT}
  abort_if_var_unset "OPENSSL_NO_OPTS" ${OPENSSL_NO_OPTS}
}

prepare_boost() {
  abort_if_var_unset "BOOST_ROOT" ${BOOST_ROOT}
  abort_if_var_unset "BOOST_VERSION" ${BOOST_VERSION}
  abort_if_var_unset "BOOST_MAJOR" ${BOOST_MAJOR}
  abort_if_var_unset "BOOST_MINOR" ${BOOST_MINOR}

  if ! [ -x "$(command -v wget)" ]; then
      echo "Error: wget is not installed."
      exit 1
  fi

  pushd ${SRC}
  echo "Checking for ${BOOST_ROOT}..."
  if [ ! -d ${BOOST_ROOT} ]; then
    prompt_msg "Downloading BOOST ${BOOST_MAJOR}_${BOOST_VERSION}_${BOOST_MINOR}"
    wget -4 -O boost.zip https://dl.bintray.com/boostorg/release/${BOOST_MAJOR}.${BOOST_VERSION}.${BOOST_MINOR}/source/boost_${BOOST_MAJOR}_${BOOST_VERSION}_${BOOST_MINOR}.zip
    unzip -qq boost.zip
    rm -f boost.zip
  fi
  pushd ${BOOST_ROOT}
  pwd
  ./bootstrap.sh
  ./b2
  ./b2 /headers
  popd
  popd
}

download_android_ndk() {
  abort_if_var_unset "NDK_VERSION" ${NDK_VERSION}
  if [ ! -f android-ndk-${NDK_VERSION}.zip ]; then
    prompt_msg "download_android_ndk: Downloading android-ndk-${NDK_VERSION}"
    wget -4 -O android-ndk-${NDK_VERSION}.zip https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-${host_os}-x86_64.zip;
    prompt_msg "download_android_ndk: Extracting NDK...wait";
    unzip -qq android-ndk-${NDK_VERSION}.zip;
  fi
}

prepare_android_toolchain() {
  abort_if_var_unset "SRC" ${SRC}
  abort_if_var_unset "NDK_VERSION" ${NDK_VERSION}
  abort_if_var_unset "os_arch" ${os_arch}
  abort_if_var_unset "android_api" ${android_api}
  pushd ${SRC}

  host_os="linux"
  if [[ "$OSTYPE" == "darwin"* ]]; then
      host_os="darwin"
  fi

  if [[ $host_os == "linux" ]]; then
      sudo apt install swig
  fi
  
  download_android_ndk

  export NDK=$PWD/android-ndk-${NDK_VERSION}
  prompt_msg "prepare_android_toolchain: NDK=${NDK}"

  # Use the prebuilt toolchain path
  export ANDROID_TOOLCHAIN=${NDK}/toolchains/llvm/prebuilt/linux-x86_64
  echo "ANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN}"
  press_any_to_continue
  popd
}

prepare_android_standalone_toolchain() {
  abort_if_var_unset "SRC" ${SRC}
  abort_if_var_unset "NDK_VERSION" ${NDK_VERSION}
  abort_if_var_unset "os_arch" ${os_arch}
  abort_if_var_unset "android_api" ${android_api}
  pushd ${SRC}

  host_os="linux"
  if [[ "$OSTYPE" == "darwin"* ]]; then
      host_os="darwin"
  fi

  if [[ $host_os == "linux" ]]; then
      sudo apt install swig
  fi
  
  download_android_ndk

  export NDK=$PWD/android-ndk-${NDK_VERSION}
  prompt_msg "NDK=${NDK}"

  if [ -d standalone_toolchain ]; then
    rm -fr standalone_toolchain
  fi

  #try this command to get path of the prebuilt toolchain in the warnings
  $NDK/build/tools/make_standalone_toolchain.py --arch ${os_arch} --api ${android_api} --stl libc++ --install-dir standalone_toolchain
  #./build/tools/make_standalone_toolchain.py --arch x86 --api 21 --stl libc++ --install-dir standalone_toolchain
  #./build/tools/make_standalone_toolchain.py --arch x86_64 --api 21 --stl libc++ --install-dir standalone_toolchain
  #./build/tools/make_standalone_toolchain.py --arch arm --api 21 --stl libc++ --install-dir standalone_toolchain
  #./build/tools/make_standalone_toolchain.py --arch arm64 --api 21 --stl libc++ --install-dir standalone_toolchain

  # Use the standalone toolchain path
  export ANDROID_TOOLCHAIN=${PWD}/standalone_toolchain
  prompt_msg "prepare_android_standalone_toolchain: ANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN}"
  popd
}

prepare_linux_toolchain() {
  echo "preparing linux toolchain..."
  sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
  sudo apt-get update -qq
  sudo apt-get install -qq g++-7 g++-7-multilib swig
  sudo apt-get install build-essential gradle
  sudo apt-get install openjdk-11-jdk-headless
  sudo apt-get install python python-dev
  echo "done preparing linux toolchain"
}

prepare_windows_x86_toolchain() {
  echo "preparing windows x86 toolchain..."
  sudo apt-get install -qq g++-mingw-w64-i686 swig
}

prepare_windows_x86_64_toolchain() {
  echo "preparing windows x86_64 toolchain..."
  sudo apt-get install -qq g++-mingw-w64-x86-64 swig
}

prepare_openssl() {
  abort_if_var_unset "SRC" ${SRC}
  abort_if_var_unset "OPENSSL_VERSION" ${OPENSSL_VERSION}
  abort_if_var_unset "OPENSSL_SOURCE" ${OPENSSL_SOURCE}
  if [ ! -d ${OPENSSL_SOURCE} ]; then
    prompt_msg "Downloading OPENSSL ${OPENSSL_VERSION} to '${OPENSSL_SOURCE}'"
    pushd ${SRC}
    #wget -nv -4 -O openssl.tar.gz https://www.openssl.org/source/openssl-1.1.1i.tar.gz
    wget -4 --no-check-certificate -O openssl.tar.gz https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
    tar xvfz openssl.tar.gz
    rm -f openssl.tar.gz
    # avoid GDI dependency in windows, fix double return statement on threads_none.c
    if [[ $os_build == "windows" ]]; then
      sed -i 's/if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333/if 0/g' ${OPENSSL_SOURCE}/crypto/cryptlib.c;
      sed -i 's/MessageBox.*//g' ${OPENSSL_SOURCE}/crypto/cryptlib.c;
      sed -i 's/return return 0;/return 0;/g' ${OPENSSL_SOURCE}/crypto/threads_none.c;
    fi
    popd
  fi
}

build_openssl() {
  abort_if_var_unset "OPENSSL_SOURCE" ${OPENSSL_SOURCE}
  abort_if_var_unset "run_openssl_configure" ${run_openssl_configure}
  prompt_msg "build_openssl: run_openssl_configure=[${run_openssl_configure}]"
  press_any_to_continue
  if [ -d ${OPENSSL_ROOT} ]; then
    rm -fr ${OPENSSL_ROOT}
  fi
  if [ -d ${OPENSSL_SOURCE} ]; then
    pushd ${OPENSSL_SOURCE}
    make clean
    $run_openssl_configure
    make -j 8
    make install_sw
    popd
  fi  
  if [[ $os_build == "windows" ]]; then
    pushd ${OPENSSL_ROOT}/lib
    if [ -L libcrypto.lib ]; then
      rm libcrypto.lib
    fi
    if [ -L libssl.lib ]; then
      rm libssl.lib
    fi
    ln -s libcrypto.a libcrypto.lib
    ln -s libssl.a libssl.lib
    popd
  fi
}

prepare_libtorrent() {
  echo "prepare_libtorrent started..."
  abort_if_var_unset "SRC" ${SRC}
  abort_if_var_unset "LIBTORRENT_ROOT" ${LIBTORRENT_ROOT}
  abort_if_var_unset "LIBTORRENT_REVISION" ${LIBTORRENT_REVISION}
  if [ ! -d ${LIBTORRENT_ROOT} ]; then
    pushd ${SRC}
    git clone https://github.com/arvidn/libtorrent
    popd
  fi 
  pushd ${LIBTORRENT_ROOT}
  prompt_msg "Checking if you have any uncommited changes"
  git status
  prompt_msg "Abort with Ctrl-C if there's pending changes above or you will lose them"
  press_any_to_continue
  git fetch origin RC_1_2
  git reset --hard ${LIBTORRENT_REVISION}
  git submodule init
  git submodule update
  make clean
  popd
  echo "prepare_libtorrent finished."
}

build_libraries() {
  abort_if_var_unset "OPENSSL_ROOT" ${OPENSSL_ROOT}
  abort_if_var_unset "SWIG" ${SWIG}
  abort_if_var_unset "os_build" ${os_build}
  abort_if_var_unset "os_arch" ${os_arch}
  abort_if_var_unset "SHARED_LIB" ${SHARED_LIB}
  abort_if_var_unset "run_bjam" ${run_bjam}
  abort_if_var_unset "run_objcopy" ${run_objcopy}
  abort_if_var_unset "run_strip" ${run_strip}
  abort_if_var_unset "run_readelf" ${run_readelf}
  set -x
  cd ${SWIG}
  if [[ $os_build == "windows" && $os_arch == "x86" ]]; then
    pwd
    sed -i 's/ JNICALL Java_com_frostwire/ JNICALL _Java_com_frostwire/g' libtorrent_jni.cpp;
  fi    
  export PATH=${PATH}:${BOOST_ROOT}/tools/build/src/engine
  echo "Added boost tools to PATH:"
  echo ${PATH}
  export OPENSSL_ROOT=${OPENSSL_ROOT}
  export LIBTORRENT_ROOT=${LIBTORRENT_ROOT}
  export BOOST_ROOT=${BOOST_ROOT}
  export BOOST_BUILD_PATH=${BOOST_ROOT}
  $run_bjam
  $run_objcopy
  $run_strip

  # fix libjlibtorrent.dll -> jlibtorrent.dll
  if [[ $os_build == "windows" ]]; then
    cp bin/release/windows/${os_arch}/libjlibtorrent.dll bin/release/windows/${os_arch}/jlibtorrent.dll
  fi
  
  cd ..

  # so that tests pass when running on mac or linux we copy the shared library to the root folder
  if [[ $os_build == "macosx" || $os_build == "linux" ]]; then
    cp swig/bin/release/${os_build}/${os_arch}/${SHARED_LIB} .
  fi
  gradle clean
  gradle build
}

cleanup_objects() {
  abort_if_var_unset "SWIG" ${SWIG}
  # cleanup (when it's finally working, enable this)
  if [ -d ${SWIG}/bin ]; then
    cd ${SWIG}/bin
    find . -type f | egrep -v '.*\.so$|.*\.dll$|.*\.dylib$|.*\.debug$' | xargs rm
    find . -empty -type d | xargs rm -r
  else
    echo ${SWIG}/bin folder not found, nothing to clean  
  fi
  cd ${SWIG}
  cd ..
  find . -type f | egrep '\d.\d.\d.\d\d.jar$'
  cd ${SWIG}
}
